#include "klabel.h"
#include "themeController.h"
#include <QPainter>
#include <QRect>
#include <QPainterPath>
#include <QDebug>
#include <QApplication>

namespace kdk {

static const int spacing = 4;
class KLabelPrivate :public QObject, public ThemeController
{
    Q_OBJECT
    Q_DECLARE_PUBLIC(KLabel)
public:
    KLabelPrivate(KLabel*parent);

protected:
    void changeTheme();
private:
    KLabel *q_ptr;
    KLabelType m_labelType;
    QPixmap m_pixmap;
    QString m_text;
    QColor m_backgroundColor;
    QColor m_fontColor;
    QIcon m_icon;
    bool m_dataHightColorFlag;
    bool m_isBackgroundFlag;
    int m_topLeftRadius;
    int m_topRightRadius;
    int m_bottomLeftRadius;
    int m_bottomRightRadius;
    int diffPointSize;
    int m_pixmapWidth;
    int m_pixmapHeight;
    bool m_isHighlightBackgroundFlag;
    bool m_wordWrap;
    bool m_isFontColor;
    bool m_isIcon;
};

KLabel::KLabel(QWidget *parent):
    QLabel(parent),
    d_ptr(new KLabelPrivate(this))
{
    Q_D(KLabel);
    int pointSize = QApplication::font().pointSize();
    connect(d->m_gsetting,&QGSettings::changed,this,[=]{
        d->changeTheme();
        int now = this->font().pointSize();
        if(now != QApplication::font().pointSize())
        {
            if(d->diffPointSize == 0)
                d->diffPointSize = now - pointSize;
            QFont font = this->font();
            font.setPointSize(d->diffPointSize + QApplication::font().pointSize());
            setFont(font);
        }
    });
}

void KLabel::setLabelType(KLabelType type)
{
    Q_D(KLabel);
    d->m_labelType = type;
}

void KLabel::setDataHightColor(bool flag)
{
    Q_D(KLabel);
    d->m_dataHightColorFlag =flag;
}

void KLabel::setPixmap(const QPixmap &pixmap)
{
    Q_D(KLabel);
    d->m_isIcon = false;
    d->m_pixmap = pixmap;
}

void KLabel::setPixmap(QIcon icon, int width, int height)
{
    Q_D(KLabel);
    d->m_isIcon = true;
    d->m_pixmapWidth = width;
    d->m_pixmapHeight = height;
    d->m_icon = icon;
}

const QPixmap *KLabel::pixmap() const
{
    Q_D(const KLabel);
    return &d->m_pixmap;
}

void KLabel::setText(const QString &str)
{
    Q_D(KLabel);
    QLabel::setText(str);
}

QString KLabel::text()
{
    Q_D(KLabel);
    return QLabel::text();
}

void KLabel::setBackgroundColor(bool flag, QColor color)
{
    Q_D(KLabel);
    if(d->m_isHighlightBackgroundFlag)
        d->m_isHighlightBackgroundFlag = false;
    d->m_isBackgroundFlag = flag;
    d->m_backgroundColor = color;
    update();
}

void KLabel::setHighlightBackground(bool flag)
{
    Q_D(KLabel);
    if(d->m_isBackgroundFlag)
        d->m_isBackgroundFlag = false;
    d->m_isHighlightBackgroundFlag = flag;
    update();
}

void KLabel::setBorderRadius(int bottomLeft, int topLeft, int topRight, int bottomRight)
{
    Q_D(KLabel);
    d->m_bottomRightRadius = bottomRight;
    d->m_topLeftRadius = topLeft;
    d->m_bottomLeftRadius = bottomLeft;
    d->m_topRightRadius = topRight;
}

void KLabel::setBorderRadius(int radius)
{
    Q_D(KLabel);
    d->m_bottomRightRadius = radius;
    d->m_topLeftRadius = radius;
    d->m_bottomLeftRadius = radius;
    d->m_topRightRadius = radius;
}

void KLabel::setWordWrap(bool flag)
{
    Q_D(KLabel);
    d->m_wordWrap =flag;
}

bool KLabel::wordWrap()
{
    Q_D(KLabel);
    return d->m_wordWrap ;
}

void KLabel::setFontColor(QColor color)
{
    Q_D(KLabel);
    d->m_fontColor = color;
    d->m_isFontColor = true;
}

void KLabel::paintEvent(QPaintEvent *event)
{
    Q_D(KLabel);
    QPainter painter(this);
    painter.setRenderHint(QPainter::SmoothPixmapTransform);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setRenderHint(QPainter::HighQualityAntialiasing);
    QColor bkgColor;
    QRect drawRect = rect();
    QRect iconRect;
    QRect textRect;

    painter.setPen(Qt::NoPen);
    QString str = text();

    //绘制背景
    QPainterPath path;
    path.moveTo(drawRect.topRight() - QPoint(d->m_topRightRadius , 0) ); //右上
    path.lineTo(drawRect.topLeft() + QPointF(d->m_topLeftRadius , 0)); //上方线
    path.quadTo(drawRect.topLeft(), drawRect.topLeft() + QPointF(0 , d->m_topLeftRadius)); //圆角
    path.lineTo(drawRect.bottomLeft() +  QPointF(0,- d->m_bottomLeftRadius)); //左方线
    path.quadTo(drawRect.bottomLeft(), drawRect.bottomLeft() + QPointF(d->m_bottomLeftRadius , 0));//圆角
    path.lineTo(drawRect.bottomRight() - QPointF(d->m_bottomRightRadius , 0));//下方线
    path.quadTo(drawRect.bottomRight(), drawRect.bottomRight() + QPointF(0, - d->m_bottomRightRadius));//圆角
    path.lineTo(drawRect.topRight() + QPointF(0, d->m_topRightRadius));//右方线
    path.quadTo(drawRect.topRight() , drawRect.topRight() - QPointF(d->m_topRightRadius, 0)); // 圆角

    switch (d->m_labelType) {
    case DataType:
        bkgColor = palette().highlight().color();
        bkgColor.setAlphaF(0.15);
        if(d->m_isBackgroundFlag)
        {
            painter.setBrush(d->m_backgroundColor);
            painter.setPen(Qt::NoPen);
        }
        else
        {
            painter.setBrush(bkgColor);
            painter.setPen(Qt::NoPen);
        }
        painter.drawPath(path);
        break;
    case NormalType:
        if(d->m_isBackgroundFlag)
            painter.setBrush(d->m_backgroundColor);
        else if(d->m_isHighlightBackgroundFlag)
            painter.setBrush(palette().highlight().color());
        else
            painter.setBrush(Qt::NoBrush);
        painter.setPen(Qt::NoPen);
        painter.drawPath(path);
        break;
    case CircleType:
        if(d->m_isBackgroundFlag)
            painter.setBrush(d->m_backgroundColor);
        else if(d->m_isHighlightBackgroundFlag)
                painter.setBrush(palette().highlight().color());
        else
            painter.setBrush(palette().button().color());
        painter.setPen(Qt::NoPen);
        painter.drawEllipse(rect());
        break;
    default:
        break;
    }

    //绘制图标和文字
    if(d->m_isIcon)
        d->m_pixmap = d->m_icon.pixmap(d->m_pixmapWidth,d->m_pixmapHeight);
    if((d->m_pixmap.size().width() != d->m_pixmapWidth || d->m_pixmap.size().height() != d->m_pixmapHeight )&& !d->m_pixmap.isNull())
        d->m_pixmap = d->m_pixmap.scaled(d->m_pixmapWidth,d->m_pixmapHeight,Qt::KeepAspectRatio, Qt::SmoothTransformation);

    QMargins margins = contentsMargins();
    if(!wordWrap())
    {
        int drawLength ;
        if(!text().isEmpty() && !d->m_pixmap.isNull())
            drawLength = d->m_pixmap.width() + spacing +fontMetrics().width(text());
        else if(!text().isEmpty() && d->m_pixmap.isNull())
            drawLength = fontMetrics().width(text());
        else if(text().isEmpty() && !d->m_pixmap.isNull())
            drawLength = d->m_pixmap.width();

        if(!text().isEmpty() && !d->m_pixmap.isNull())
        {

            int drawLength = d->m_pixmap.width() + spacing +fontMetrics().width(text());
            if(drawRect.width() > drawLength )
            {
                iconRect = QRect(/*drawRect.center().x() - drawLength/2*/drawRect.x() + margins.left(),
                                 drawRect.center().y() - d->m_pixmap.height()/2 + margins.top(),
                                 d->m_pixmap.width(),
                                 d->m_pixmap.height());
                textRect = QRect(iconRect.right() + spacing,
                                 /*drawRect.center().y() - fontMetrics().height()/2 +*/ margins.top(),
                                 fontMetrics().width(text()) + 1,
                                 /*fontMetrics().height()*/
                                 drawRect.height());
                setToolTip("");

            }
            else
            {
                iconRect = QRect(/*drawRect.x()*/drawRect.x() + margins.left(),
                                 drawRect.center().y() - d->m_pixmap.height()/2 + margins.top(),
                                 d->m_pixmap.width(),
                                 d->m_pixmap.height());
                textRect = QRect(iconRect.right() + spacing,
                                 /*drawRect.center().y() - fontMetrics().height()/2 +*/ margins.top(),
                                 drawRect.width() - spacing - iconRect.width(),
                                 /*fontMetrics().height()*/
                                 drawRect.height());
                setToolTip(str);
                str = fontMetrics().elidedText(str,Qt::ElideRight,textRect.width());
            }
        }
        else
        {
            if(text().isEmpty())
            {
                iconRect = QRect(drawRect.center().x() - drawLength/2 + margins.left(),
                                 drawRect.center().y() - d->m_pixmap.height()/2 + margins.top(),
                                 d->m_pixmap.width(),
                                 d->m_pixmap.height());
            }
            else
            {
                int drawLength =fontMetrics().width(text());
                if(drawRect.width() > drawLength )
                {
                    textRect = QRect(/*drawRect.center().x() - drawLength/2*/drawRect.x() + margins.left(),
                                     /*drawRect.center().y() - fontMetrics().height()/2 +*/ margins.top(),
                                     fontMetrics().width(text()) + 2,
                                     /*fontMetrics().height()*/
                                     drawRect.height());
                    setToolTip("");
                }
                else
                {
                    textRect = QRect(drawRect.x() + margins.left(),
                                     /*drawRect.center().y() - fontMetrics().height()/2 + */margins.top(),
                                     drawRect.width(),
                                     /*fontMetrics().height()*/
                                     drawRect.height());
                    setToolTip(str);
                    str = fontMetrics().elidedText(str,Qt::ElideRight,textRect.width());
                }
            }
        }

        if(d->m_dataHightColorFlag)
        {
            d->m_pixmap = ThemeController::drawColoredPixmap(d->m_pixmap,palette().highlight().color());
            if(d->m_isFontColor)
                painter.setPen(d->m_fontColor);
            else
                painter.setPen(palette().highlight().color());
        }
        else if(d->m_isBackgroundFlag || d->m_isHighlightBackgroundFlag)
        {
            d->m_pixmap = ThemeController::drawSymbolicColoredPixmap(d->m_pixmap);
            if(d->m_isFontColor)
                painter.setPen(d->m_fontColor);
            else
                painter.setPen(palette().windowText().color());
        }
        else {
            if(d->m_isFontColor)
                painter.setPen(d->m_fontColor);
            else
                painter.setPen(palette().windowText().color());
            if(ThemeController::isPixmapPureColor(d->m_pixmap))
            {
                if(ThemeController::themeMode() == DarkTheme)
                    d->m_pixmap = ThemeController::drawColoredPixmap(d->m_pixmap,Qt::white);
                else
                    d->m_pixmap = ThemeController::drawColoredPixmap(d->m_pixmap,palette().windowText().color());
            }
        }

        if(alignment() == Qt::AlignCenter)
        {
            if(!text().isEmpty() && !d->m_pixmap.isNull())
            {
                iconRect.moveLeft(drawRect.center().x() - drawLength/2);
                textRect.moveLeft(iconRect.right()  + spacing);
            }
            else
            {
                if(text().isEmpty())
                    iconRect.moveLeft(drawRect.center().x() - drawLength/2);
                else
                    textRect.moveLeft(drawRect.center().x() - drawLength/2);
            }
        }
        painter.drawText(textRect,Qt::AlignVCenter,str);
        painter.drawPixmap(iconRect,d->m_pixmap);
    }
    else
    {
        QFontMetrics metrics(this->font());

        int lineHeight = metrics.height();
        int xPos = drawRect.left(); // 起始x位置
        int yPos = metrics.leading()+metrics.ascent(); // 起始y位置

        while (!str.isEmpty())
        {
            QString line;
            int widthUsed = 0;
            if(rect().height() > (yPos + lineHeight))
            {
                QChar ch;
                for (int i = 0; i < str.length(); ++i)
                {
                    ch = str[i];
                    int charWidth = metrics.horizontalAdvance(ch);
                    if(ch == '\n')
                    {
                        str.remove(ch);
                        break;
                    }
                    if (widthUsed + charWidth > this->width()+2 )
                    {
                        break; // 当前行已满，开始新行
                    }

                    line += ch;
                    widthUsed += charWidth;
                }
                if(d->m_isFontColor)
                    painter.setPen(d->m_fontColor);
                else
                    painter.setPen(palette().windowText().color());
                painter.drawText(xPos,yPos,line);
                yPos += lineHeight;
                setToolTip("");
            }
            else
            {
                line = fontMetrics().elidedText(str,Qt::ElideRight,rect().width());
                if(d->m_isFontColor)
                    painter.setPen(d->m_fontColor);
                else
                    painter.setPen(palette().windowText().color());
                if(line != text())
                    setToolTip(text());
                painter.drawText(xPos,yPos,line);
                break;
            }
            // 准备下一行
            str = str.mid(line.length());
        }
    }
}

void KLabel::resizeEvent(QResizeEvent *event)
{
    Q_D(KLabel);
    int height = d->m_pixmapHeight > fontMetrics().height() ? d->m_pixmapHeight : fontMetrics().height();
    if(height > size().height())
    {
        setMinimumHeight(height);
    }
    QLabel::resizeEvent(event);
}

QSize KLabel::sizeHint() const
{
    Q_D(const KLabel);
    return QLabel::sizeHint();
}

KLabelPrivate::KLabelPrivate(KLabel *parent)
    :q_ptr(parent),
    m_isBackgroundFlag(false),
    m_dataHightColorFlag(false),
    m_bottomRightRadius(6),
    m_topLeftRadius(6),
    m_bottomLeftRadius(6),
    m_topRightRadius(6),
    diffPointSize(0),
    m_pixmapWidth(16),
    m_pixmapHeight(16),
    m_isHighlightBackgroundFlag(false),
    m_wordWrap(false),
    m_isFontColor(false),
    m_isIcon(false)
{
    Q_Q(KLabel);
    m_labelType = NormalType;
}

void KLabelPrivate::changeTheme()
{
    Q_Q(KLabel);
    initThemeStyle();
}

}


#include "klabel.moc"
#include "moc_klabel.cpp"
